home *** CD-ROM | disk | FTP | other *** search
/ Amiga Plus 2000 #5 / Amiga Plus CD - 2000 - No. 5.iso / Tools / Dev / FPSE_src / mdec.c < prev    next >
C/C++ Source or Header  |  2000-01-01  |  8KB  |  304 lines

  1. /*
  2.     MDEC decoder engine
  3.     ===================
  4.  
  5.     Written by BERO
  6. */
  7.  
  8. #include "fpse.h"
  9.  
  10. #define INVERT_RGB      0
  11.  
  12. #if INVERT_RGB==0
  13. #define R   0
  14. #define G   1
  15. #define B   2
  16. #else
  17. #define R   2
  18. #define G   1
  19. #define B   0
  20. #endif
  21.  
  22. #define   RAMADDR(addr) ((void*)&ram[(addr)&0x1fffff])
  23. #define   DCTSIZE2  64
  24.  
  25. static UINT16 *rl2blk(BLOCK *blk,UINT16 *mdec_rl);
  26. static void iqtab_init(int *iqtab,UINT8 *iq_y);
  27. static void round_init(void);
  28. static void yuv2rgb24(BLOCK *blk,UINT8  *image);
  29. static void yuv2rgb15(BLOCK *blk,UINT16 *image);
  30.  
  31. static struct {
  32.      UINT32 command;
  33.      UINT32 status;
  34.      UINT16 *rl;
  35.      int rlsize;
  36. } mdec;
  37.  
  38. static int iq_y[DCTSIZE2],iq_uv[DCTSIZE2];
  39.  
  40. void mdec_init(void)
  41. {
  42.     mdec.rl = RAMADDR(0x100000); /* Init to some value */
  43.     mdec.command = 0;
  44.     mdec.status = 0;
  45.     round_init();
  46. }
  47.  
  48. void mdec0_write(UINT32 data)
  49. {
  50.     mdec.command = data;
  51.     if ((data&0xf5ff0000)==0x30000000) {
  52.         mdec.rlsize = data&0xffff;
  53.     }
  54. }
  55.  
  56. void mdec1_write(UINT32 data)
  57. {
  58. }
  59.  
  60. UINT32 mdec0_read(void)
  61. {
  62.     return 0;
  63. }
  64.  
  65. UINT32 mdec1_read(void)
  66. {
  67.     return mdec.status;
  68. }
  69.  
  70. void dma0_exec(UINT32 adr,UINT32 bcr,UINT32 chcr)
  71. {
  72.      int cmd = mdec.command;
  73.      int size;
  74.  
  75.      if (chcr!=0x01000201) return;
  76.  
  77.      size = (bcr>>16)*(bcr&0xffff);
  78.  
  79.      if (cmd==0x60000000) {
  80.           /* cosine table */
  81.      //   printf("cos table");
  82.      } else
  83.      if (cmd==0x40000001) {
  84.           /* quantize table */
  85.           unsigned char *p = RAMADDR(adr);
  86.           iqtab_init(iq_y,p);
  87.           iqtab_init(iq_uv,p+64);
  88.      //   printf("quantize table");
  89.      } else
  90.      if ((cmd&0xf5ff0000)==0x30000000) {
  91.           /* run/value data */
  92.           mdec.rl = RAMADDR(adr);
  93.      //   printf("data");
  94.      }
  95.      else {
  96.      //   printf("unknown cmd");
  97.      }
  98. }
  99.  
  100. void dma1_exec(UINT32 adr,UINT32 bcr,UINT32 chcr)
  101. {
  102.      int size;
  103.  
  104.      if (chcr!=0x01000200) return;
  105.  
  106.      size = (bcr>>16)*(bcr&0xffff);
  107.  
  108.         CompileFlush(adr,adr+size*4);
  109.      /* decode */
  110.   {
  111.      BLOCK blk[DCTSIZE2*6];
  112.      UINT16    *image = RAMADDR(adr);
  113.      int blocksize;
  114.      if (mdec.command&0x08000000) blocksize = 16*16;
  115.      else blocksize = 24*16;
  116.  
  117.      for(;size>0;size-=blocksize/2,image+=blocksize) {
  118.           mdec.rl = rl2blk(blk,mdec.rl);
  119.           if (mdec.command&0x08000000)
  120.                      yuv2rgb15(blk,image);
  121.           else yuv2rgb24(blk,(unsigned char *)image);
  122.      }
  123.   }
  124. }
  125.  
  126. /* de-quantize / inverse-dct / yuv->rgb */
  127.  
  128.  
  129. #define   RUNOF(a)  ((a)>>10)
  130. #define   VALOF(a)  (((int)(a)<<(32-10))>>(32-10))
  131.  
  132. static int zscan[DCTSIZE2] = {
  133.      0 ,1 ,8 ,16,9 ,2 ,3 ,10,
  134.      17,24,32,25,18,11,4 ,5 ,
  135.      12,19,26,33,40,48,41,34,
  136.      27,20,13,6 ,7 ,14,21,28,
  137.      35,42,49,56,57,50,43,36,
  138.      29,22,15,23,30,37,44,51,
  139.      58,59,52,45,38,31,39,46,
  140.      53,60,61,54,47,55,62,63
  141. };
  142.  
  143. static int aanscales[DCTSIZE2] = {
  144.        /* precomputed values scaled up by 14 bits */
  145.        16384, 22725, 21407, 19266, 16384, 12873,  8867,  4520,
  146.        22725, 31521, 29692, 26722, 22725, 17855, 12299,  6270,
  147.        21407, 29692, 27969, 25172, 21407, 16819, 11585,  5906,
  148.        19266, 26722, 25172, 22654, 19266, 15137, 10426,  5315,
  149.        16384, 22725, 21407, 19266, 16384, 12873,  8867,  4520,
  150.        12873, 17855, 16819, 15137, 12873, 10114,  6967,  3552,
  151.         8867, 12299, 11585, 10426,  8867,  6967,  4799,  2446,
  152.         4520,  6270,  5906,  5315,  4520,  3552,  2446,  1247
  153. };
  154.  
  155. static void iqtab_init(int *iqtab,unsigned char *iq_y)
  156. {
  157. #define CONST_BITS 14
  158. #define   IFAST_SCALE_BITS 2
  159.      int i;
  160.      for(i=0;i<DCTSIZE2;i++) {
  161.           iqtab[i] =iq_y[i]*aanscales[i]>>(CONST_BITS-IFAST_SCALE_BITS);
  162.      }
  163. }
  164.  
  165.  
  166. static UINT16 *rl2blk(BLOCK *blk, UINT16 *mdec_rl)
  167. {
  168.      int i,k,q_scale,rl;
  169.      int *iqtab;
  170. #define   EOB  0xfe00
  171.  
  172.      memset(blk,0,6*DCTSIZE2*sizeof(BLOCK));
  173.      for(i=0;i<6;i++) {
  174.           if (i<2) iqtab = iq_uv;
  175.           else iqtab = iq_y;
  176.           rl = SWAP16(*mdec_rl++);
  177.      //   if (rl==EOB) printf("err");
  178.           q_scale = RUNOF(rl);
  179.           blk[0] = iqtab[0]*VALOF(rl);
  180.           k = 0;
  181.           for(;;) {
  182.                rl = SWAP16(*mdec_rl++);
  183.                if (rl==EOB) break;
  184.                k += RUNOF(rl)+1;
  185.                         if (k > 63) break;
  186.                 blk[zscan[k]] = iqtab[zscan[k]]*q_scale*VALOF(rl)/8;
  187.      //        blk[zscan[k]] = iqtab[k]*q_scale*VALOF(rl);
  188.           }
  189.  
  190.           idct(blk,k+1);
  191.           
  192.           blk+=DCTSIZE2;
  193.      }
  194.      return mdec_rl;
  195. }
  196.  
  197. #define   SHIFT       12
  198. #define   toFIX(a)    (int)((a)*(1<<SHIFT))
  199. #define   toINT(a)    ((a)>>SHIFT)
  200. #define   FIX_1       toFIX(1)
  201. #define   MULR(a)     toINT((a)*toFIX(1.402))
  202. #define   MULG(a)     toINT((a)*toFIX(-0.3437))
  203. #define   MULG2(a)    toINT((a)*toFIX(-0.7143))
  204. #define   MULB(a)     toINT((a)*toFIX(1.772))
  205.  
  206. #define   RGB15(r,g,b)   ( (((r)>>3)<<10)|(((g)>>3)<<5)|((b)>>3) )
  207. #define   ROUND(c)  roundtbl[(c)+128+256]
  208.  
  209. static UINT8 roundtbl[256*3];
  210.  
  211. static void round_init(void)
  212. {
  213.      int i;
  214.      for(i=0;i<256;i++) {
  215.           roundtbl[i]=0;
  216.           roundtbl[i+256]=i;
  217.           roundtbl[i+512]=255;
  218.      }
  219. }
  220.  
  221. static void yuv2rgb15(BLOCK *blk, UINT16 *image)
  222. {
  223.      int x,yy;
  224.      BLOCK *yblk = blk+DCTSIZE2*2;
  225.      for(yy=0;yy<16;yy+=2,blk+=4,yblk+=8,image+=8+16) {
  226.           if (yy==8) yblk+=DCTSIZE2;
  227.           for(x=0;x<4;x++,blk++,yblk+=2,image+=2) {
  228.                int r0,b0,g0,y;
  229.                r0 = MULR(blk[DCTSIZE2]); /* cr */
  230.                g0 = MULG(blk[0])+MULG2(blk[DCTSIZE2]);
  231.                b0 = MULB(blk[0]); /* cb */
  232.                y = yblk[0];
  233.                image[0] = SWAP16(RGB15(ROUND(r0+y),ROUND(g0+y),ROUND(b0+y)));
  234.                y = yblk[1];
  235.                image[1] = SWAP16(RGB15(ROUND(r0+y),ROUND(g0+y),ROUND(b0+y)));
  236.                y = yblk[8];
  237.                image[16] = SWAP16(RGB15(ROUND(r0+y),ROUND(g0+y),ROUND(b0+y)));
  238.                y = yblk[9];
  239.                image[17] = SWAP16(RGB15(ROUND(r0+y),ROUND(g0+y),ROUND(b0+y)));
  240.                r0 = MULR(blk[4+DCTSIZE2]);
  241.                g0 = MULG(blk[4])+MULG2(blk[4+DCTSIZE2]);
  242.                b0 = MULB(blk[4]);
  243.                y = yblk[DCTSIZE2+0];
  244.                image[8+0] = SWAP16(RGB15(ROUND(r0+y),ROUND(g0+y),ROUND(b0+y)));
  245.                y = yblk[DCTSIZE2+1];
  246.                image[8+1] = SWAP16(RGB15(ROUND(r0+y),ROUND(g0+y),ROUND(b0+y)));
  247.                y = yblk[DCTSIZE2+8];
  248.                image[8+16] = SWAP16(RGB15(ROUND(r0+y),ROUND(g0+y),ROUND(b0+y)));
  249.                y = yblk[DCTSIZE2+9];
  250.                image[8+17] = SWAP16(RGB15(ROUND(r0+y),ROUND(g0+y),ROUND(b0+y)));
  251.           }
  252.      }
  253. }
  254.  
  255. static void yuv2rgb24(BLOCK *blk, UINT8 *image)
  256. {
  257.      int x,yy;
  258.      BLOCK *yblk = blk+DCTSIZE2*2;
  259.      for(yy=0;yy<16;yy+=2,blk+=4,yblk+=8,image+=(8+16)*3) {
  260.           if (yy==8) yblk+=DCTSIZE2;
  261.           for(x=0;x<4;x++,blk++,yblk+=2,image+=2*3) {
  262.                int r0,b0,g0,y;
  263.                r0 = MULR(blk[DCTSIZE2]); /* cr */
  264.                g0 = MULG(blk[0])+MULG2(blk[DCTSIZE2]);
  265.                b0 = MULB(blk[0]); /* cb */
  266.                y = yblk[0];
  267.                image[0*3+R] = ROUND(r0+y);
  268.                image[0*3+G] = ROUND(g0+y);
  269.                image[0*3+B] = ROUND(b0+y);
  270.                y = yblk[1];
  271.                image[1*3+R] = ROUND(r0+y);
  272.                image[1*3+G] = ROUND(g0+y);
  273.                image[1*3+B] = ROUND(b0+y);
  274.                y = yblk[8];
  275.                image[16*3+R] = ROUND(r0+y);
  276.                image[16*3+G] = ROUND(g0+y);
  277.                image[16*3+B] = ROUND(b0+y);
  278.                y = yblk[9];
  279.                image[17*3+R] = ROUND(r0+y);
  280.                image[17*3+G] = ROUND(g0+y);
  281.                image[17*3+B] = ROUND(b0+y);
  282.  
  283.                r0 = MULR(blk[4+DCTSIZE2]);
  284.                g0 = MULG(blk[4])+MULG2(blk[4+DCTSIZE2]);
  285.                b0 = MULB(blk[4]);
  286.                y = yblk[DCTSIZE2+0];
  287.                image[(8+0)*3+R] = ROUND(r0+y);
  288.                image[(8+0)*3+G] = ROUND(g0+y);
  289.                image[(8+0)*3+B] = ROUND(b0+y);
  290.                y = yblk[DCTSIZE2+1];
  291.                image[(8+1)*3+R] = ROUND(r0+y);
  292.                image[(8+1)*3+G] = ROUND(g0+y);
  293.                image[(8+1)*3+B] = ROUND(b0+y);
  294.                y = yblk[DCTSIZE2+8];
  295.                image[(8+16)*3+R] = ROUND(r0+y);
  296.                image[(8+16)*3+G] = ROUND(g0+y);
  297.                image[(8+16)*3+B] = ROUND(b0+y);
  298.                y = yblk[DCTSIZE2+9];
  299.                image[(8+17)*3+R] = ROUND(r0+y);
  300.                image[(8+17)*3+G] = ROUND(g0+y);
  301.                image[(8+17)*3+B] = ROUND(b0+y);
  302.           }
  303.      }
  304. }